package gupao.concurrency.threads;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jol.info.ClassLayout;

@Slf4j
public class SyncLockHeaderMarkword {

    private final static Object obj = new Object();

    public static void main(String[] args) throws Exception {
//        biasedLockTest();
//        lightLockTest();
        heavyLockTest();
    }

    public static void heavyLockTest() throws InterruptedException {
        System.out.println("heavyLockTest=====");
        System.out.println("No Lock:");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        synchronized (obj){
            System.out.println("Biased Lock:");
            System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        }
        System.out.println("Light Lock:");
        Thread t1 = new Thread(() -> {
            synchronized (obj){
                System.out.println(Thread.currentThread().getName());
                System.out.println(ClassLayout.parseInstance(obj).toPrintable());
            }
        });
        t1.start();
        t1.join();

        Thread t2 = new Thread(() -> {
            synchronized (obj){
                System.out.println(Thread.currentThread().getName());
                System.out.println(ClassLayout.parseInstance(obj).toPrintable());
            }
        });
        t2.start();
        t1.join();
        System.out.println("Heavy Lock:");

        new Thread(() -> {
            synchronized (obj){
                Utils.sleepIgnoreExp(3000);
                System.out.println(Thread.currentThread().getName() + ":");
                System.out.println(ClassLayout.parseInstance(obj).toPrintable());
            }
        }).start();

        synchronized (obj){
            System.out.println(Thread.currentThread().getName() + ":");
            System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        }

        Utils.sleepIgnoreExp(3000);
    }

    public static void lightLockTest() throws InterruptedException {
        System.out.println("lightLockTest=====");
        System.out.println("No Lock:");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());

        synchronized (obj){
            System.out.println("Biased Lock:");
            System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        }

        Thread t1 = new Thread(() -> {
            synchronized (obj){
                System.out.println(Thread.currentThread().getName());
                System.out.println(ClassLayout.parseInstance(obj).toPrintable());
            }
        });
        t1.start();
        t1.join();

        Thread t2 = new Thread(() -> {
            synchronized (obj){
                System.out.println(Thread.currentThread().getName());
                System.out.println(ClassLayout.parseInstance(obj).toPrintable());
            }
        });
        t2.start();
        t1.join();
    }


    public static void biasedLockTest(){
        System.out.println("No Lock:");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        synchronized (obj){
            System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        }
    }
}
